# __init__方法：初始化方法
class Test:
    def __init__(self, name):
        print("这是初始化方法")
        self.name = name
        print(f"{self.name}")

t = Test("Tom")

# __new__方法：实例化对象时第一个调用的方法，优先于__init__调用
# 使用__new__来实现单例模式
class Singleton:
    __instance = None

    def __new__(cls, *args, **kwargs):
        if cls.__instance is None:
            cls.__instance = super().__new__(cls)
        return cls.__instance

    def __init__(self, name):
        print("这是初始化方法")
        self.name = name
        print(f"{self.name}")

a = Singleton("Tom")
b = Singleton("Jerry")
# Singleton类实现了单例模式，a和b实际上是同一个对象实例。这里虽然两次调用Singleton(),但是new方法返回的是同一个实例，init方法被调用两次
# 第二次的Jerry会覆盖第一次的Tom
print(a.name)
print(b.name)

print("=" * 50)
# 实现文件操作上下文管理器
class OpenFile:
    def __init__(self, filename, mode, encoding):
        self.filename = filename
        self.mode = mode
        self.encoding = encoding

    def __enter__(self):
        self.file = open(self.filename, self.mode, encoding=self.encoding)
        return self.file

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.file.close()

with OpenFile("../resources/file.txt", "r", encoding="utf-8") as f:
    print(f.read())


print("=" * 50)
# __call__：允许对象像函数一样调用
class Test1:
    def __init__(self, name):
        self.name = name

    def __call__(self, *args, **kwargs):
        print(f"这是__call__方法，参数为：{args}")
        print(f"这是__call__方法，参数为：{kwargs}")
        print(f"这是__call__方法，参数为：{self.name}")

t = Test1("张三")
t()

print("=" * 50)
# 使用类来实现装饰器
class MyDecorator:
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        print("开始执行")
        result = self.func(*args, **kwargs)
        print("结束执行")
        return result

# 相当于 test = MyDecorator(test)
# 由于MyDecorator实现了__call__方法，所以test()会调用__call__方法
@MyDecorator
def test(name, age):
    print(f"这是被装饰的函数，参数为：{name} {age}")
    return "hello"

test("张三",18)

print("=" * 50)
# __str__
class Test2:
    def __init__(self, name):
        self.name = name

    def __str__(self):
        return f"这是__str__方法，参数为：{self.name}"

t2 = Test2("张三")
print(t2)   # 这是__str__方法，参数为：张三

print("=" * 50)
# 自定义对象的对法运算
class Test3:
    def __init__(self, name,age):
        self.name = name
        self.age = age

    def __add__(self,other):
        print("这是__add__方法")
        return self.age + other.age

    def __gt__(self, other):
        print("这是__gt__方法")
        return self.age > other.age

    def __ge__(self, other):
        print("这是__ge__方法")
        return self.age >= other.age

zs = Test3("张三",18)
ls = Test3("李四",20)
print(zs + ls)
print("张三年龄大于李四？", zs > ls)
print("张三年龄是否大于等于李四？", zs >= ls)